package com.yql.commonextend.utils;

import com.yql.commonextend.config.TripleDesConfig;
import com.yql.commonextend.exception.CryptoException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;

public class TripleDesUtils {

    private static final Logger log = LoggerFactory.getLogger(TripleDesUtils.class);

    //加密密钥 key size must be 16 or 24 bytes
    private byte[] key = TripleDesConfig.getPubKey().getBytes();
    //初始化向量 IV must be 8 bytes long
    private byte[] ivs = TripleDesConfig.getPubIvs().getBytes();


    public static final String ISONAME = "UTF-8";

    public static final String UTFNAME = "UTF-8";

    static {
        if (Security.getProvider("BC") == null) {
            Security.addProvider(new BouncyCastleProvider());
        }
    }

    /**
     * 设置密钥
     *
     * @param newkey size must be 16 or 24 bytes
     */
    public void setKey(byte[] newkey) {
        try {
            key = newkey;
        } catch (Exception e) {
            log.error("set key error", e);
        }
    }

    /**
     * 设置向量
     *
     * @param newivs must be 8 bytes
     */
    public void setIvs(byte[] newivs) {
        try {
            ivs = newivs;
        } catch (Exception e) {
            log.error("set ivs error", e);
        }
    }


    /**
     * DES解密
     *
     * @param srcStr 加密密文
     * @return
     */
    public String TripleDesDecrypt(String srcStr) {
        SecretKeySpec desKey = new SecretKeySpec(key, "DESede");
        IvParameterSpec iv = new IvParameterSpec(ivs);
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("DESede/CBC/PKCS7Padding", "BC");
        } catch (NoSuchAlgorithmException e) {
            log.error("TripleDesDecrypt NoSuchAlgorithmException异常", e);
        } catch (NoSuchProviderException e) {
            log.error("TripleDesDecrypt NoSuchProviderException异常", e);
        } catch (NoSuchPaddingException e) {
            log.error("TripleDesDecrypt NoSuchPaddingException异常", e);
        }

        try {
            cipher.init(Cipher.DECRYPT_MODE, desKey, iv);
        } catch (InvalidKeyException e) {
            log.error("TripleDesDecrypt InvalidKeyException异常", e);
        } catch (InvalidAlgorithmParameterException e) {
            log.error("TripleDesDecrypt InvalidAlgorithmParameterException异常", e);
        }

        byte[] cipherText = null;
        try {
            cipherText = cipher.doFinal(Base64.decode(srcStr));
        } catch (IllegalBlockSizeException e) {
            log.error("TripleDesDecrypt IllegalBlockSizeException异常", e);
            throw new CryptoException(e);//参数解密失败，返回非法操作
        } catch (BadPaddingException e) {
            log.error("TripleDesDecrypt BadPaddingException异常", e);
            throw new CryptoException(e);//参数解密失败，返回非法操作
        }

        try {
            return new String(cipherText, UTFNAME);
        } catch (UnsupportedEncodingException e) {
            log.error("TripleDesDecrypt UnsupportedEncodingException异常", e);
            return null;
        }

    }

    /**
     * DES加密
     *
     * @param srcStr 加密原文
     * @return
     */
    public String TripleDesEncrypt(String srcStr) {
        SecretKeySpec desKey = new SecretKeySpec(key, "DESede");
        IvParameterSpec iv = new IvParameterSpec(ivs);
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("DESede/CBC/PKCS7Padding", "BC");
        } catch (NoSuchAlgorithmException e) {
            log.error("TripleDesEncrypt NoSuchAlgorithmException异常", e);
        } catch (NoSuchProviderException e) {
            log.error("TripleDesEncrypt NoSuchProviderException异常", e);
        } catch (NoSuchPaddingException e) {
            log.error("TripleDesEncrypt NoSuchPaddingException异常", e);
        }

        try {
            cipher.init(Cipher.ENCRYPT_MODE, desKey, iv);
        } catch (InvalidKeyException e) {
            log.error("TripleDesEncrypt InvalidKeyException异常", e);
        } catch (InvalidAlgorithmParameterException e) {
            log.error("TripleDesEncrypt InvalidAlgorithmParameterException异常", e);
        }

        byte[] cipherText = null;
        try {
            cipherText = cipher.doFinal(srcStr.getBytes(UTFNAME));
        } catch (IllegalBlockSizeException e) {
            log.error("TripleDesEncrypt IllegalBlockSizeException异常", e);
        } catch (BadPaddingException e) {
            log.error("TripleDesEncrypt BadPaddingException异常", e);
        } catch (UnsupportedEncodingException e) {
            log.error("TripleDesEncrypt UnsupportedEncodingException异常", e);
        }

        return new String(Base64.encode(cipherText));
    }

}
